home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 41 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  5.2 KB

  1. From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
  2. Message-ID: <9601130029.11343@mulga.cs.mu.OZ.AU>
  3. X-Original-Date: Sat, 13 Jan 1996 11:29:56 +1100
  4. Path: in1.uu.net!bounce-back
  5. Date: 13 Jan 96 00:56:57 GMT
  6. Approved: fjh@cs.mu.oz.au
  7. Newsgroups: comp.std.c++
  8. Subject: Re: Overloading 'operator new': errors in MSVC 2.0 or not?
  9. Organization: Computer Science, University of Melbourne, Australia
  10. References: <m0talmh-000FHlC@redline.ru>
  11. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  12.     iQBFAgUBMPcDqeEDnX0m9pzZAQHpRwF9FyJEcMLGVf/AfD2Ocg2+Jp8Y7Mfv091d
  13.     dUXSh6sufDuAOoqPyr3MywYCyVKJQkd3
  14.     =L1f7
  15.  
  16. mike <mike@redline.ru> writes:
  17.  
  18. >I think I've discovered some errors in Microsoft Visual C++ 2.0 compiler.
  19. >
  20. >1) Suppose we want to overload global 'operator new':
  21. >
  22. >void* operator new (size_t size, MemoryAllocator* palloc)
  23. >{
  24. >    // Allocate memory using special allocator
  25. >    return palloc->alloc (size);
  26. >}
  27. >
  28. >How to delete object allocated by this function?
  29. >We can't overload 'operator delete' (according to ARM 5.3.4, 12.5).
  30.  
  31. The ARM is out-of-date on this one; the committee has changed things so
  32. you are indeed allowed to overload operator delete.  This is basically
  33. just for specifying cleanup if an exception is thrown, since there is
  34. no nice syntax for invoking the destructor and the overloaded operator
  35. delete.  To ensure that you do get correct cleanup in an expression such
  36. as `new (palloc) Foo' if the `Foo::Foo()' constructor throws an exception,
  37. you should define an appropriate overloaded operator delete:
  38.  
  39.     void* operator delete (void *p, MemoryAllocator* palloc)
  40.     {
  41.         palloc->free (p);    // free memory
  42.     }
  43.  
  44. >We must write something like this:
  45. >
  46. >void Delete_SomeClass (SomeClass* p, MemoryAllocator* palloc)
  47. >{
  48. >    p->~SomeClass ();    // direct destructor call
  49. >    palloc->free (p);    // free memory
  50. >}
  51.  
  52. Yep, you will still need this, even if you overload operator delete
  53. as above; the syntax `delete (palloc) p' will not work.
  54.  
  55. >It works, but it is too tiresome to write such function for every class.
  56. >A better way is to use template function:
  57. >
  58. >template <class Type>
  59. >void Delete (Type* p, MemoryAllocator* palloc)
  60. >{
  61. >    p->~Type ();         // direct destructor call - is it allowed here?
  62. >    palloc->free (p);    // free memory
  63. >}
  64.  
  65. Yes, the direct destructor call is allowed.
  66.  
  67. >But if I try to write
  68. >
  69. >    MemoryAllocator alloc;
  70. >    SomeClass* p = new (&alloc) SomeClass;
  71. >    Delete (p, &alloc);
  72. >
  73. >then compiler writes something like
  74. >filename(line#) : error C2300: 'SomeClass' : class does
  75. >not have a destructor called '~Type'
  76. >
  77. >Is it an error of compiler?
  78.  
  79. Yes, your code is fine - you need to get a better compiler.
  80.  
  81. >2) Again, let's overload global 'operator new' with default parameter:
  82. >
  83. >void* operator new (size_t size, MemoryAllocator* palloc = NULL)
  84. >{
  85. >    return palloc ? palloc->alloc (size) : malloc (size);
  86. >}
  87.  
  88. That is not correct, since it won't do the right thing for zero-sized
  89. allocations.  You should write
  90.  
  91.     void* operator new (size_t size, MemoryAllocator* palloc = NULL)
  92.     {
  93.       return palloc ? palloc->alloc (size) : malloc (size == 0 ? 1 : size);
  94.     }                         ^^^^^^^^^^^^^^^^^^^^
  95.  
  96. to make sure that you return a distinct address for each zero-sized
  97. allocation.
  98.  
  99. Also, the use of a default parameter probably doesn't do what you want.
  100. Rather than replacing the built-in global `operator new(size_t)', the
  101. two versions will coexist.  The September 95 draft standard says
  102. (see 5.3.4 [expr.new]) that in an expression like `new int', the
  103. "appropriate" allocation function will be called, but in this case it
  104. is not clear which allocation function is appropriate.  A compiler
  105. might always call the global `operator new(size_t)' rather than your
  106. version.  Or it might try to perform overload resolution, which would
  107. mean that if you #include <new.h>, which declares the global `operator
  108. new(size_t)', then any expression like `new int' will result in an
  109. ambiguity error.  Or it might consider such expressions ambiguous even
  110. if you don't #include <new.h>.
  111.  
  112. >If I write now
  113. >
  114. >    char* p = new char [100];
  115. >
  116. >then compiler (it seems) must invoke operator new (100, NULL). But when I've
  117. >inspected assembler listing, I discovered that compiler invokes standard
  118. >library version of 'operator new' rather than overloaded one.
  119. >To correct it, I have to write
  120. >
  121. >void* operator new (size_t size, MemoryAllocator* palloc)
  122. >{
  123. >    return palloc ? palloc->alloc (size) : malloc (size);
  124. >}
  125. >void* operator new (size_t size)
  126. >{
  127. >    return operator new (size, NULL);
  128. >}
  129. >
  130. >Now it works OK. Is it also a compiler error?
  131.  
  132. No.  For
  133.  
  134.     char* p = new char [100];
  135.  
  136. the compiler should invoke `operator new [] (size_t)' rather than
  137. `operator new (size_t)'.  The default behaviour of `operator new [] (size_t)'
  138. is to invoke `operator new (size_t)'.  This explains what you are seeing.
  139.  
  140. Anyhow, defining a (possibly inline) `operator new (size_t)' is a much
  141. better idea than using a default operator, because it avoids the possible
  142. problems I mentioned above.
  143.  
  144. --
  145. Fergus Henderson                 WWW: http://www.cs.mu.oz.au/~fjh
  146. fjh@cs.mu.oz.au                  PGP: finger fjh@128.250.37.3
  147. ---
  148. [ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  149.   Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  150.   is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
  151.